package com.gaokuo.es;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gaokuo.es.compose.*;
import com.gaokuo.es.property.FuncFieldNameUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;

import java.io.IOException;

@Slf4j
public class SearchTest {
    RestHighLevelClient client = new RestHighLevelClient(
            RestClient.builder(new HttpHost("10.10.20.112", 9200, "http"))
    );
    ObjectMapper mapper = new ObjectMapper();
    @Test
    public void all() throws IOException {
        SearchRequest request = new SearchRequest();
        request.indices("person");
        request.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));
        log.info("req:{}",request.source());
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        log.info("TotalHits===>{}",hits.getTotalHits());
        log.info("Took===>{}",response.getTook());

        hits.forEach(h ->{
            log.info("===>"+h.getSourceAsString());
        });
    }
    @Test
    public void simple() throws IOException {
        SearchRequest request = new SearchRequest();
        request.indices("person");

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //等于
        boolQuery.filter(QueryBuilders.termsQuery(FuncFieldNameUtil.get(Person::getSex),"女"));
        //等于
        boolQuery.must(QueryBuilders.termsQuery(FuncFieldNameUtil.get(Person::getName),"p1"));
        //范围
        boolQuery.filter(QueryBuilders.rangeQuery(FuncFieldNameUtil.get(Person::getAge)).gte(20));
        //friendArr in
        boolQuery.must(QueryBuilders.termsQuery(FuncFieldNameUtil.get(Person::getFriendArr),"pf3","pf0"));
        //friendArr not in
        boolQuery.mustNot(QueryBuilders.termsQuery(FuncFieldNameUtil.get(Person::getFriendArr),"pf1","pf4"));
        //and (... or ...)
        boolQuery.should(QueryBuilders.termsQuery(FuncFieldNameUtil.get(Person::getName),"p1"));
        boolQuery.should(QueryBuilders.termsQuery(FuncFieldNameUtil.get(Person::getName),"c"));
        //有should的地方必有minimumShouldMatch才可实现or
        boolQuery.minimumShouldMatch(1);
        //排序
        request.source(new SearchSourceBuilder().query(boolQuery).sort(FuncFieldNameUtil.get(Person::getAge), SortOrder.DESC));
        log.info("req:{}",request.source());
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        log.info("TotalHits===>{}",hits.getTotalHits());
        log.info("Took===>{}",response.getTook());

        hits.forEach(h ->{
            log.info("===>"+h.getSourceAsString());
        });
    }


    @Test
    public void compose() throws IOException {
        ComposeConditionNode conditionNode1 = new ComposeConditionNode("name", ConditionEnum.term,"p1");
        ComposeConditionNode conditionNode2 = new ComposeConditionNode(ComposeBindEnum.and,"age",ConditionEnum.gte,"21");
        ComposeConditionNode conditionNode3 = new ComposeConditionNode("age",ConditionEnum.lt,"50");
        ComposeConditionNode conditionNode4 = new ComposeConditionNode(ComposeBindEnum.or,"sex",ConditionEnum.term,"女");
        ComposeConditionNode conditionNode5 = new ComposeConditionNode(ComposeBindEnum.and,"say",ConditionEnum.match,"1");

        ComposeNestedNode composeNestedNode1 = new ComposeNestedNode();
        composeNestedNode1.addChildNode(conditionNode1).addChildNode(conditionNode2);
        ComposeNestedNode composeNestedNode2 = new ComposeNestedNode(ComposeBindEnum.and);
        composeNestedNode2.addChildNode(conditionNode3).addChildNode(conditionNode4);

        ComposeNestedNode composeNestedNode = new ComposeNestedNode(ComposeBindEnum.and);
        composeNestedNode.addChildNode(composeNestedNode1);
        composeNestedNode.addChildNode(conditionNode5);
        composeNestedNode.addChildNode(composeNestedNode2);


        DefaultEsComposeSearch composeSearch = new DefaultEsComposeSearch(new DefaultConditionBuild());


        BoolQueryBuilder boolQueryBuilder = composeSearch.getBoolQuery(composeNestedNode);
        SearchRequest request = new SearchRequest();
        request.indices("person");
        request.source(new SearchSourceBuilder().query(boolQueryBuilder).sort(FuncFieldNameUtil.get(Person::getAge), SortOrder.DESC));
        log.info("req:{}",request.source());
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();

        log.info("TotalHits===>{}",hits.getTotalHits());
        log.info("Took===>{}",response.getTook());

        hits.forEach(h ->{
            log.info("===>"+h.getSourceAsString());
        });
    }

}
